package lamer;

import java.io.IOException;
import java.util.Random;

import irio.gamer.gamer;
import utils.Vec;
import Logic.Galaxy;
import Logic.GalaxyComponent;
import Logic.Renderlist;

public class Likelihood {

	public int imageSize = 128;
	public int wavelength = 5000;

	public int currentStage = 0;
	public LamerParams currentParams = new LamerParams();
	public LamerParams prevParams = new LamerParams();
	Random rnd = new Random();
	
	private double steps = 0;
	private double z = 0;
	
	public void Initialize() {
		Galaxy galaxy = currentParams.galaxy;
		steps = 0;
		galaxy.filename = "Likelihood.gax";
		galaxy.initialized = true;
		galaxy.no_arms.x = 2;
		galaxy.arm1.x = 0;
		galaxy.arm2.x = 3.14159;
		galaxy.innerTwirl.x = 0;
		galaxy.bulge_axis.set(1,1,1);
		galaxy.bulge_dust.x = 0;
		galaxy.winding_B.x = 0.5;
		galaxy.winding_N.x = 0.5;

		GalaxyComponent bulge = new GalaxyComponent();
		bulge.type.x = 0;
		bulge.z0.x = 1.0;
		bulge.r0.x = 1.0;
		bulge.armstrength.x = 10;
		bulge.component_no = 1;
		bulge.active.x = 1;
		bulge.intensity_modifier.x = 3;
		bulge.spectrum.x = 0;
		galaxy.components.add(bulge);
	
		GalaxyComponent disk = new GalaxyComponent();
		disk.type.x =1;
		disk.component_no = 2;
		disk.z0.x = 0.01;
		disk.r0.x = 0.35;
		disk.active.x = 1;
		disk.armstrength.x = 0.5;
		disk.intensity_modifier.x = 2;
		disk.spectrum.x = 0;
		disk.noiseTilt.x = 0.0;
		galaxy.components.add(disk);
		
	}
	
	public double getLikelihood()  {
		
		String s = "bin/gutil chisq " + LSettings.dataFile +".fits " + LSettings.outputFile+".fits";
		Process p;
		try {
			p = Runtime.getRuntime().exec(s);
			return gamer.getReturnValueProcess(p);		

		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return -1;
	}
	
	private double prevLikelihood = 1E-50;
	private double curLikelihood = 1E10;
	
	private void VaryParams() {
		if (currentStage == 0) {
			currentParams.rp.camera.z += rnd.nextGaussian()*2;//*(currentParams.rp.camera.z*0.3 +2);
			currentParams.rp.camera.z = Math.abs(currentParams.rp.camera.z);
			currentParams.galaxy.winding_N.x +=rnd.nextGaussian()*1.0f;
			currentParams.galaxy.winding_N.x = Math.abs(currentParams.galaxy.winding_N.x);
			Vec.tmp.set(1,1,1);
			Vec.tmp.randomize(rnd);
			currentParams.orientation.addDirect(Vec.tmp, 0.5);
			currentParams.orientation.normDirect();
		}
	}
	
	public void Step() {
		VaryParams();
		Realize();
		double chisq = getLikelihood();
		curLikelihood = Math.exp(-chisq);
		double L = curLikelihood/prevLikelihood;
		System.out.println("L:"+ L + "  with z " + currentParams.rp.camera.z + " and org z " + prevParams.rp.camera.z);
		boolean accept = false;
		
		if (L>1) accept = true;
		else
		{
			double r = rnd.nextDouble();
			/*if (r<L) 
				accept = true;*/
		}
		if (accept) {
			System.out.println("ACCEPTED!");
			prevLikelihood = curLikelihood;
			prevParams.CopyFrom(currentParams);
			steps++;
			z+=currentParams.rp.camera.z;
			currentParams.SaveStep((int)steps);
			//System.out.println("Avg z:"  +z / steps);
			ImageFrame.Fits2Bmp(LSettings.outputFile);
			ImageFrame.reload();

		}
		else {
			currentParams.CopyFrom(prevParams);

		}
	}
	
	public void Realize() {
		
		currentParams.rp.Save(LSettings.renderingParams);
		String lamerScene = "scenes/lamer.rl";
		System.out.println("Saving to " + currentParams.galaxy.filename);
		currentParams.galaxy.Save(currentParams.galaxy.filename);
		Renderlist.createLamer(lamerScene, currentParams.galaxy.filename, currentParams.orientation);
		String s = Lamer.gamerParams.mpiCommand + " -n 4 bin/gamer lamer_renderparameters.ini " +
			 lamerScene + " " + imageSize + " " + (int) wavelength
				+ " " + LSettings.outputFile + ".fits";
		 System.out.println(s);

		
		
		try {
			Process p = Runtime.getRuntime().exec(s);
			gamer.waitforProcess(p);
			ImageFrame.Normalize(LSettings.outputFile);

		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

	
	
	
}
